﻿using System;
using BrnMall.Core;
using BrnMall.Manager.Manager.Ship;
using System.Diagnostics;
using System.Collections.Generic;
using Ship.DaDa;

namespace BrnMall.Services
{
    /// <summary>
    /// 配送服务(如：达达配送)
    /// </summary>
    public class Ships
    {

        #region  达达订单管理

        /// <summary>
        /// 返回配送费用 (不含自定义的配送费)
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public static JsonModel<QueryFeeModel> GetShipFee(OrderInfo orderInfo)
        {
            //获订单送地址
            var address = Regions.GetRegionById(orderInfo.RegionId);
            if (address == null) return new JsonModel<QueryFeeModel>() { Code = 500, Msg = "地址不存在" };

            //根据地址，获取城市代码
            var codeModel = DaDaHelper.GetCityCode(address.CityName);
            if (codeModel == null) return new JsonModel<QueryFeeModel>() { Code = 500, Msg = "订单地址不存在" };

            //根据地址，转换坐标
            var locationInfo = Map.GaoDe.Web.SDK.GetLocation(address.CityName, orderInfo.Address);
            if (locationInfo == null) return new JsonModel<QueryFeeModel>() { Code = 500, Msg = "地址转换坐标失败" };

            string[] location = locationInfo.location.Split(',');
            var param = GetOrderParam(orderInfo, codeModel.CityCode, Convert.ToDouble(location[0]), Convert.ToDouble(location[1]));
            return DaDaHelper.QueryFee(param);
        }

        /// <summary>
        /// 返回配送费用 (含自定义的配送费)
        /// </summary>
        /// <param name="storeId"></param>
        /// <param name="cityName"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        public static JsonModel<QueryFeeModel> GetShipFee(int storeId, string cityName, string address)
        {

            //根据地址，获取城市代码
            var codeModel = DaDaHelper.GetCityCode(cityName);
            if (codeModel == null) return new JsonModel<QueryFeeModel>() { Code = 500, Msg = "订单地址不存在" };

            //根据地址，转换坐标
            var locationInfo = Map.GaoDe.Web.SDK.GetLocation(cityName, address);
            if (locationInfo == null) return new JsonModel<QueryFeeModel>() { Code = 500, Msg = "找不到配送地址" };

            string[] location = locationInfo.location.Split(',');

            OrderInfo orderInfo = new OrderInfo()
            {
                StoreId = storeId,
                OSN = string.Format("{0}{1}", storeId, DateTime.Now.ToString("yyyyMMddHHmmss")),
                Address = address,
                Consignee = storeId.ToString(),
                OrderAmount = 50,
                Mobile = "13600001111"
            };
            var param = GetOrderParam(orderInfo, codeModel.CityCode, Convert.ToDouble(location[0]), Convert.ToDouble(location[1]));
            var model = DaDaHelper.QueryFee(param);

            if (!IsSuccess(model))
                return model;

            //自定义配送费
            var config = ShipConfigManager.GetByStoreId(storeId);
            if (config != null && config.ShipMoney > 0)
            {
                double distance = model.Result.Distance * 0.001;
                if (distance > config.MaxDistance)
                    return new JsonModel<QueryFeeModel>() { Code = 500, Msg = $"您的配送距离为{distance}公里,超出{config.MaxDistance}公里不能配送" };

                //设置自定义配送费
                model.Result.Fee = (double)config.ShipMoney;
            }
            return model;
        }

        /// <summary>
        /// 添加达达的配送订单
        /// </summary>
        /// <param name="order"></param>
        /// <param name="shipFee"></param>
        /// <returns></returns>
        public static string AddOrder(OrderInfo orderInfo, int storeUid)
        {
            var cashModel = ShipCashManager.GetInfo(orderInfo.StoreId);
            if (cashModel == null || cashModel.ShopState != 1)
                return "未开通达达配送";

            var address = Regions.GetRegionById(orderInfo.RegionId);
            if (address == null)
                return "配送地址不存在";

            //根据地址，获取城市代码
            var codeModel = DaDaHelper.GetCityCode(address.CityName);
            if (codeModel == null) return $"{address.CityName}未开通达达配送";

            //根据地址，转换坐标
            var locationInfo = Map.GaoDe.Web.SDK.GetLocation(address.CityName, orderInfo.Address);
            if (locationInfo == null)
                return "找不到配送地址";

            //查询配送费用(此处不能用店铺设置的配送费，因为达达是按平台方式扣费，必须跟达达实际扣费的价格同步)
            var feeModel = GetShipFee(orderInfo);
            if (!DaDaHelper.IsSuccess(feeModel))
                return feeModel.Msg;

            //先扣费
            var cashMsg = ShipOrders.ConsumeCash(storeUid, orderInfo.StoreId, (decimal)feeModel.Result.Fee, "配送费用", orderInfo.OSN);
            if (cashMsg != "")
                return cashMsg;

            //后派单
            string[] location = locationInfo.location.Split(',');
            var param = GetOrderParam(orderInfo, codeModel.CityCode, Convert.ToDouble(location[0]), Convert.ToDouble(location[1]));
            var model = DaDaHelper.AddOrder(param);
            if (!DaDaHelper.IsSuccess(model))
            {
                //配送失败，退回费用
                ShipOrders.AddCash(storeUid, orderInfo.StoreId, (decimal)feeModel.Result.Fee, "配送退回");
                return model.Msg;
            }

            return string.Empty;
        }

        /// <summary>
        /// 配送进度、骑手距离、配送费用
        /// </summary>
        public static GetOrderModel GetStatus(string osn)
        {
            return DaDaHelper.GetOrder(osn);
        }

        /// <summary>
        /// 骑手接受订单
        /// </summary>
        public static void AcceptOrder(OrderInfo orderInfo)
        {
            Log($"配送回调:骑手接受订单: AcceptOrder({orderInfo.OSN})");
            //订单进度
            CreateOrderAction(orderInfo.Oid, 0, OrderActionType.Cancel, "骑手接受订单");

            //达达扣运营平台的费用记录
            var record = ShipRecordManager.GetByOSN(orderInfo.StoreId, orderInfo.OSN);
            var orderMoney = record == null ? 0 : record.Amount;

            if (!ShipOrders.AddSysRecord(orderMoney, 2, "达达扣费", orderInfo.OSN))
            {
                Log($"Ships.AcceptOrder({orderInfo.OSN}) 达达扣费明细添加失败!", true);
            }
        }

        /// <summary>
        /// 订单配送中
        /// </summary>
        public static void WorkOrder(OrderInfo orderInfo, string name, string phone)
        {
            Log($"配送回调:骑手已取餐: WorkOrder({orderInfo.OSN},'{name}','{phone}')");
            CreateOrderAction(orderInfo.Oid, 0, OrderActionType.Cancel, $"骑手已取餐（骑手：{name} {phone}）");
        }

        /// <summary>
        /// 完成订单
        /// </summary>
        public static void FinishOrder(OrderInfo orderInfo)
        {
            Log($"配送回调:骑手完成订单: FinishOrder({orderInfo.OSN})");
            if (orderInfo.OrderState != (int)OrderState.Sended)
            {
                Trace.TraceError(string.Format("Ships.FinishOrder({0}) 骑手完成订单回调错误：订单当前不能收货", orderInfo.OSN));
                return;
            }

            var partUserInfo = Users.GetPartUserById(orderInfo.Uid);
            //收货
            Orders.ReceiveOrder(ref partUserInfo, orderInfo, DateTime.Now, WebHelper.GetIP());

            CreateOrderAction(orderInfo.Oid, orderInfo.Uid, OrderActionType.Cancel, "您已经收货");
        }

        /// <summary>
        /// 取消配送订单
        /// </summary>
        public static void CacelOrder(OrderInfo orderInfo)
        {
            Log($"配送回调:取消订单: CacelOrder({orderInfo.OSN})");
            CreateOrderAction(orderInfo.Oid, orderInfo.Uid, OrderActionType.Cancel, "配送已取消");
        }

        /// <summary>
        /// 取消配送订单,后台调用
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <param name="reason_id">取消理由ID</param>
        /// <param name="cancel_reason">其他取消原因</param>
        public static string CacelOrder(OrderInfo orderInfo, int reason_id, string cancel_reason)
        {
            //取消操作
            var jsonModel = DaDaHelper.CacelOrder(orderInfo.OSN, reason_id, cancel_reason);
            if (!DaDaHelper.IsSuccess(jsonModel))
            {
                return jsonModel.Msg;   //取消失败
            }

            //计算退款费用
            var recordModel = ShipRecordManager.GetByOSN(orderInfo.StoreId, orderInfo.OSN);
            decimal amount = recordModel != null ? recordModel.Amount *-1: 0;   //扣款金额            
            decimal deduct_fee = jsonModel.Result.deduct_fee;                   //违约金

            if (deduct_fee > 0)
                amount = amount - deduct_fee;                                   //实际退款金额 = 配送费 - 违约金

            amount = amount < 0 ? 0 : amount;                                   //负数判断

            //退款，并添加退款记录
            ShipOrders.AddCash(orderInfo.Uid, orderInfo.StoreId, amount, "配送退款", orderInfo.OSN);
            Trace.TraceInformation($"Ships.CacelOrder({orderInfo.OSN},{reason_id},{cancel_reason}) 配送已取消,GetByOSN({orderInfo.StoreId}, {orderInfo.OSN}),退款金额:{amount},违约金:{deduct_fee}");
            return string.Empty;
        }

        /// <summary>
        /// 配送过期
        /// </summary>
        /// <param name="order_id"></param>
        public static void ExpireOrder(OrderInfo orderInfo)
        {
            Trace.TraceInformation(string.Format("Ships.ExpireOrder({0}) 配送过期!", orderInfo.OSN));
            CreateOrderAction(orderInfo.Oid, 0, OrderActionType.Cancel, "配送过期");
        }

        /// <summary>
        /// 获取取消配送理由
        /// </summary>
        /// <returns></returns>
        public static List<CacelReasonModel> GetCacelReason()
        {
            return DaDaHelper.GetCacelReason();
        }
        #endregion

        #region 达达门店管理

        /// <summary>
        /// 添加门店
        /// </summary>
        public static string AddShop(StoreInfo storeInfo, int storeUid)
        {
            var address = Regions.GetRegionById(storeInfo.RegionId);
            if (address == null) return "地址不存在";
            
            //根据地址，获取城市代码
            var codeModel = DaDaHelper.GetCityCode(address.CityName);
            if (codeModel == null) return $"{address.CityName}暂不支持达达配送";

            //根据地址，获取坐标
            var locInfo = Map.GaoDe.Web.SDK.GetLocation(address.CityName, storeInfo.Address);
            if (locInfo == null) return "找不到门店地址";

            //创建门店
            string[] location = locInfo.location.Split(',');

            var param = GetShopParam(storeInfo, codeModel.CityName, address.Name, location[0], location[1]);
            var shopModel = DaDaHelper.AddShop(param);

            if (shopModel == null) return "达达门店创建失败";

            var shopState = 0;
            if (shopModel.success > 0)
            {
                shopState = 1;          //创建成功
            }
            else if (shopModel.FailedList != null)
            {
                var failModel = shopModel.FailedList.Find(x => x.shopName == storeInfo.Name);
                if (failModel != null)
                {
                    if (failModel.msg.Contains("已存在"))
                        shopState = 1;          //之前已创建过，状态也标记为已开通
                    else
                        return failModel.msg;   //创建失败，返回错误消息
                }
                else
                    return "达达门店创建失败";
            }

            ShipOrders.AddOrUpdateShopState(storeUid, storeInfo.StoreId, shopState);
            return string.Empty;
        }


        /// <summary>
        /// 返回门店
        /// </summary>
        public static object GetShop(int storeId)
        {
            return DaDaHelper.GetShop(storeId.ToString());
        }

        #endregion

        #region 余额管理
        
        /// <summary>
        /// 查询余额
        /// </summary>
        /// <param name="category">查询运费账户类型（1：运费账户；2：红包账户，3：所有）</param>
        /// <returns></returns>
        public static BalanceModel GetBalance(int category = 3)
        {
            return DaDaHelper.GetBalance(category);
        }

        #endregion

        #region 其他方法

        /// <summary>
        /// 达达自动派单
        /// </summary>
        /// <param name="orderInfo"></param>
        /// <param name="time_end"></param>
        public static void AutoShip(OrderInfo orderInfo, string time_end)
        {
            Log($"自动配送：开始 oid={orderInfo.Oid},osn={orderInfo.OSN}");

            var shipConfig = ShipConfigManager.GetByStoreId(orderInfo.StoreId);
            //是否自动配送
            if (shipConfig == null || shipConfig.IsAutoShip != 1)
            {
                Log($"自动配送：失败,未设置自动配送,osn={orderInfo.OSN}"); return;
            }

            var partUserInfo = Users.GetPartUserById(orderInfo.Uid);
            var realName = partUserInfo != null ? partUserInfo.NickName : "";

            //是否是餐饮模板
            if (!Stores.IsSessionApplication(partUserInfo.StoreAppId))
            {
                Log($"自动配送：失败,非餐饮模板,osn={orderInfo.OSN}"); return;
            }

            //添加订单配送
            var errMsg = Ships.AddOrder(orderInfo, orderInfo.StoreId);
            if (!errMsg.Equals(""))
            {
                Log($"自动配送：失败," + errMsg + ",osn={orderInfo.OSN}"); return;
            }

            var shipCompany = ShipCompanies.GetDaDaShip();
            //更改订单状态
            AdminOrders.SendOrder(orderInfo.Oid, OrderState.Sended, "未填", shipCompany.ShipCoId, shipCompany.Name, DateTime.Now);
            OrderActions.CreateOrderAction(new OrderActionInfo()
            {
                Oid = orderInfo.Oid,
                Uid = orderInfo.Uid,
                RealName = realName,
                ActionType = (int)OrderActionType.Send,
                ActionTime = TypeHelper.StringToDateTime(time_end),
                ActionDes = $"您的订单已经发货，发货方式为:{shipCompany.Name}，等待骑手接单"
            });

            Log("自动配送：完成");
        }

        /// <summary>
        /// 返回结果是否正常
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool IsSuccess<T>(JsonModel<T> t)
        {
            return DaDaHelper.IsSuccess(t);
        }

        public static void Log(string content, bool isError = false)
        {
            var path = System.Web.HttpContext.Current.Server.MapPath("/log/");
            var filename = string.Format("ship_{0}.txt", DateTime.Now.ToString("yyyy_MM_dd"));

            using (var sw = new System.IO.StreamWriter(path + filename, true))
            {
                sw.WriteLine(DateTime.Now.ToString() + "\t" + content);
            }

            if (isError)
                Trace.TraceError(content);
            else
                Trace.TraceInformation(content);
        }

        /// <summary>
        /// 店铺是否开通了门店
        /// </summary>
        /// <param name="storeId"></param>
        /// <returns></returns>
        public static bool ShopExists(int storeId)
        {
            var cash = ShipCashManager.GetInfo(storeId);
            if (cash == null || cash.ShopState != 1)
                return false;

            return true;
        }
        #endregion

        #region 私有方法

        /// <summary>
        /// 创建订单行为
        /// </summary>
        static void CreateOrderAction(int oid, int uid, OrderActionType orderActionType, string actionDes)
        {
            var realName = uid > 0 ? AdminUsers.GetUserDetailById(uid).RealName : "系统";
            OrderActions.CreateOrderAction(new OrderActionInfo()
            {
                Oid = oid,
                Uid = uid,
                RealName = realName,
                ActionType = (int)orderActionType,
                ActionTime = DateTime.Now,
                ActionDes = actionDes
            });
        }
        
        /// <summary>
        /// 订单参数
        /// </summary>
        /// <param name="order"></param>
        /// <param name="city_code"></param>
        /// <param name="receiver_lat"></param>
        /// <param name="receiver_lng"></param>
        /// <returns></returns>
        static Dictionary<string, object> GetOrderParam(OrderInfo order, string city_code, double receiver_lng, double receiver_lat)
        {
            var param = new Dictionary<string, object>();

            //门店编号，门店创建后可在门店列表和单页查看
            param.Add("shop_no", order.StoreId);
            //第三方订单ID
            param.Add("origin_id", order.OSN);
            //订单金额
            param.Add("cargo_price", order.OrderAmount);
            //收货人姓名
            param.Add("receiver_name", order.Consignee);
            //收货人地址
            param.Add("receiver_address", order.Address);
            //收货人手机号（手机号和座机号必填一项）
            param.Add("receiver_phone", order.Mobile);

            //订单所在城市的code
            param.Add("city_code", city_code);
            //收货人地址维度（高德坐标系）
            param.Add("receiver_lat", receiver_lat);
            //收货人地址经度（高德坐标系）
            param.Add("receiver_lng", receiver_lng);
            //是否需要垫付 1:是 0:否 (垫付订单金额，非运费)
            param.Add("is_prepay", 0);
            return param;
        }

        /// <summary>
        /// 门店参数
        /// </summary>
        /// <param name="info"></param>
        /// <param name="city_name"></param>
        /// <param name="longitude"></param>
        /// <param name="latitude"></param>
        /// <returns></returns>
        static List<Dictionary<string, object>> GetShopParam(StoreInfo info, string city_name,string area_name, string longitude, string latitude)
        {
            var list = new List<Dictionary<string, object>>();
            var param = new Dictionary<string, object>();
            
            //门店编码,可自定义,但必须唯一;若不填写,则系统自动生成
            param.Add("origin_shop_id", info.StoreId);
            //门店名称
            param.Add("station_name", info.Name);
            //城市名称(如,上海)
            param.Add("city_name", city_name);
            //区域名称(如,浦东新区)
            param.Add("area_name", area_name);
            //门店地址
            param.Add("station_address", info.Address);
            //门店经度
            param.Add("lng", longitude);
            //门店纬度
            param.Add("lat", latitude);
            //联系人姓名
            param.Add("contact_name", info.Name);
            //电话
            param.Add("phone", string.IsNullOrEmpty(info.Phone) ? info.Mobile : info.Phone);

            //门店业务
            param.Add("business", "1");
            list.Add(param);
            return list;
        }
        
        #endregion
    }
}
